package com.pan.admin.generator.service;

import com.gitee.apanlh.util.base.IteratorUtils;
import com.gitee.apanlh.util.io.IOUtils;
import com.gitee.apanlh.util.log.Log;
import com.gitee.apanlh.util.valid.ValidParam;
import com.gitee.apanlh.web.model.vo.RequestVO;
import com.pan.admin.common.constant.Constants;
import com.pan.admin.common.utils.DateUtils;
import com.pan.admin.common.utils.SecurityUtils;
import com.pan.admin.generator.constant.ApiGenEnum;
import com.pan.admin.generator.context.ApiGenContext;
import com.pan.admin.generator.entity.ApiGenConfigPO;
import com.pan.admin.generator.entity.ApiGenField;
import com.pan.admin.generator.entity.ApiGenTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
public class ApiGenServiceImpl implements ApiGenService {

    @Autowired
    private ApiGenContext apiGenContext;
    @Autowired
    private ApiGenConfigService apiGenConfigService;
    @Autowired
    private ApiGenWorkBankService apiGenWorkBankService;

    @Override
    public Map<String, String> preview(RequestVO requestVO, ApiGenEnum apiGenEnum) {
        //  获取模板对象
        ApiGenTemplate apiGenTemplate = apiGenContext.getTemplate(requestVO, apiGenEnum);
        //  获取视图
        Map<String, String> viewTemplate = apiGenContext.getViewTemplate(apiGenTemplate, apiGenEnum);
        return viewTemplate;
    }

    @Override
    public byte[] generate(RequestVO requestVO, ApiGenEnum apiGenEnum) {
        //  获取模板对象
        ApiGenTemplate apiGenTemplate = apiGenContext.getTemplate(requestVO, apiGenEnum);

        //  映射词库保存
        Thread.startVirtualThread(() -> {
            //  撞库映射字段
            List<ApiGenField> listGenDataExchangeField = apiGenTemplate.getListGenDataExchangeField();
            apiGenWorkBankService.insertMappingWorkBank(listGenDataExchangeField);
            //  进件映射字段
            List<ApiGenField> listGenApplyField = apiGenTemplate.getListGenApplyField();
            apiGenWorkBankService.insertMappingWorkBank(listGenApplyField);
        });

        //  配置保存
        String username = SecurityUtils.getUsername();
        Thread.startVirtualThread(() -> {
            ApiGenConfigPO apiGenConfigPO = new ApiGenConfigPO();
            apiGenConfigPO.setConfigName(apiGenTemplate.getCustomChineseName());
            apiGenConfigPO.setConfigText(requestVO.getBody());
            apiGenConfigPO.setGenType(apiGenTemplate.getApiGenType());
            apiGenConfigPO.setCreateTime(DateUtils.getNowDate());
            apiGenConfigPO.setCreateBy(username);
            apiGenConfigPO.setHashCode(String.valueOf(apiGenConfigPO.hashCode()));
            //  验证哈希值
            ApiGenConfigPO apiGenConfigByHashCode = apiGenConfigService.getByHashCode(apiGenConfigPO.getHashCode());
            if (ValidParam.isNull(apiGenConfigByHashCode)) {
                apiGenConfigService.insert(apiGenConfigPO);
            }
        });

        //  获取视图-导出
        Map<String, String> viewTemplate = apiGenContext.getViewTemplate(apiGenTemplate, apiGenEnum);
        //  导出
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        IteratorUtils.entrySet(viewTemplate, ((templateName, renderText) -> {
            //  获取自定义主体名称
            String customName = apiGenTemplate.getCustomName();
            try {
                // 添加到zip
                String fileName = apiGenContext.getTemplateFileName(templateName, customName, apiGenEnum);
                zip.putNextEntry(new ZipEntry(fileName));
                IOUtils.write(renderText, zip, Constants.UTF8, false);
                zip.flush();
                zip.closeEntry();
            } catch (IOException e) {
                Log.get().info("渲染模板失败，文件名：{}", templateName.substring(0, templateName.indexOf('.')), e);
            }
        }));
        IOUtils.close(zip);
        return outputStream.toByteArray();
    }
}
